#include "keys.c"
#include "uart.c"
#include <REGX52.H>
/**
 * 4个楼层，楼层灯指示电梯位置，按键等待电梯到达
 * 横向4灯代表电梯要到达的楼层，按键按下对应楼层灯亮。
 * 程序需要记录当前电梯是上行还是下行。停靠对应楼层，让对应楼层灯闪烁。
 */
// 存放电梯的按键按下状态
unsigned char elevator_button_status[] = {0, 0, 0, 0};
unsigned char floor_button_status_up[] = {0, 0, 0, 0};
unsigned char floor_button_status_down[] = {0, 0, 0, 0};

#define ELEVATOR_STATUS_UP 99
#define ELEVATOR_STATUS_DOWN 98
#define ELEVATOR_STATUS_WAITING 97

struct
{
    unsigned char floor; // 0,1,2,3 对应楼层1,2,3,4
    unsigned char status;
} ELEVATOR;

#define ELEVATOR_FLOOR_1 0
#define ELEVATOR_FLOOR_2 1
#define ELEVATOR_FLOOR_3 2
#define ELEVATOR_FLOOR_4 3
#define FLOOR_1_UP 4
#define FLOOR_2_DOWN 5
#define FLOOR_2_UP 6
#define FLOOR_3_DOWN 7
#define FLOOR_3_UP 8
#define FLOOR_4_DOWN 9

sbit LED_ELEVATOR_1 = P2 ^ 4;
sbit LED_ELEVATOR_2 = P2 ^ 5;
sbit LED_ELEVATOR_3 = P2 ^ 6;
sbit LED_ELEVATOR_4 = P2 ^ 7;
sbit LED_FLOOR_1_UP = P3 ^ 2;
sbit LED_FLOOR_2_DOWN = P3 ^ 3;
sbit LED_FLOOR_2_UP = P3 ^ 4;
sbit LED_FLOOR_3_DOWN = P3 ^ 5;
sbit LED_FLOOR_3_UP = P3 ^ 6;
sbit LED_FLOOR_4_DOWN = P3 ^ 7;

sbit LED_FLOOR_1 = P2 ^ 0;
sbit LED_FLOOR_2 = P2 ^ 1;
sbit LED_FLOOR_3 = P2 ^ 2;
sbit LED_FLOOR_4 = P2 ^ 3;

void delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for (i = 0; i < ms; i++)
    {
        for (j = 0; j < 123; j++)
            ;
    }
}

void print_arr(unsigned char arr[])
{
    unsigned char i;
    for (i = 0; i < 4; i++)
    {
        printf("%d ", (int)arr[i]);
    }
    printf("\n");
}

void process_button()
{
    unsigned char press = key_scan();
    if (press != 0xFF)
    {
        printf("%d\n", (int)press);
    }

    switch (press)
    {
    case ELEVATOR_FLOOR_1:
        LED_ELEVATOR_1 = 0;
        elevator_button_status[0] = 1;
        break;
    case ELEVATOR_FLOOR_2:
        LED_ELEVATOR_2 = 0;
        elevator_button_status[1] = 1;
        break;
    case ELEVATOR_FLOOR_3:
        LED_ELEVATOR_3 = 0;
        elevator_button_status[2] = 1;
        break;
    case ELEVATOR_FLOOR_4:
        LED_ELEVATOR_4 = 0;
        elevator_button_status[3] = 1;
        break;
    case FLOOR_1_UP:
        LED_FLOOR_1_UP = 0;
        floor_button_status_up[0] = 1;
        break;
    case FLOOR_2_UP:
        LED_FLOOR_2_UP = 0;
        floor_button_status_up[1] = 1;
        break;
    case FLOOR_3_UP:
        LED_FLOOR_3_UP = 0;
        floor_button_status_up[2] = 1;
        break;
    case FLOOR_2_DOWN:
        LED_FLOOR_2_DOWN = 0;
        floor_button_status_down[1] = 1;
        break;
    case FLOOR_3_DOWN:
        LED_FLOOR_3_DOWN = 0;
        floor_button_status_down[2] = 1;
        break;
    case FLOOR_4_DOWN:
        LED_FLOOR_4_DOWN = 0;
        floor_button_status_down[3] = 1;
        break;
    default:
        break;
    }
}

void elevator_open()
{
    unsigned char i;
    LED_FLOOR_1 = 1;
    LED_FLOOR_2 = 1;
    LED_FLOOR_3 = 1;
    LED_FLOOR_4 = 1;
    switch (ELEVATOR.floor)
    {
    case 0:
        for (i = 0; i < 3; i++)
        {
            LED_FLOOR_1 = 0;
            delay_ms(300);
            LED_FLOOR_1 = 1;
            delay_ms(300);
        }
        LED_ELEVATOR_1 = 1;
        elevator_button_status[ELEVATOR.floor] = 0;
        if (ELEVATOR.status == ELEVATOR_STATUS_UP)
        {
            LED_FLOOR_1_UP = 1;
            floor_button_status_up[ELEVATOR.floor] = 0;
        }
        break;
    case 1:
        for (i = 0; i < 3; i++)
        {
            LED_FLOOR_2 = 0;
            delay_ms(300);
            LED_FLOOR_2 = 1;
            delay_ms(300);
        }
        LED_ELEVATOR_2 = 1;
        elevator_button_status[ELEVATOR.floor] = 0;
        if (ELEVATOR.status == ELEVATOR_STATUS_UP)
        {
            LED_FLOOR_2_UP = 1;
            floor_button_status_up[ELEVATOR.floor] = 0;
        }
        else if (ELEVATOR.status == ELEVATOR_STATUS_DOWN)
        {
            LED_FLOOR_2_DOWN = 1;
            floor_button_status_down[ELEVATOR.floor] = 0;
        }
        break;
    case 2:
        for (i = 0; i < 3; i++)
        {
            LED_FLOOR_3 = 0;
            delay_ms(300);
            LED_FLOOR_3 = 1;
            delay_ms(300);
        }
        LED_ELEVATOR_3 = 1;
        elevator_button_status[ELEVATOR.floor] = 0;
        if (ELEVATOR.status == ELEVATOR_STATUS_UP)
        {
            LED_FLOOR_3_UP = 1;
            floor_button_status_up[ELEVATOR.floor] = 0;
        }
        else if (ELEVATOR.status == ELEVATOR_STATUS_DOWN)
        {
            LED_FLOOR_3_DOWN = 1;
            floor_button_status_down[ELEVATOR.floor] = 0;
        }
        break;
    case 3:
        for (i = 0; i < 3; i++)
        {
            LED_FLOOR_4 = 0;
            delay_ms(300);
            LED_FLOOR_4 = 1;
            delay_ms(300);
        }
        LED_ELEVATOR_4 = 1;
        elevator_button_status[ELEVATOR.floor] = 0;
        if (ELEVATOR.status == ELEVATOR_STATUS_DOWN)
        {
            LED_FLOOR_4_DOWN = 1;
            floor_button_status_down[ELEVATOR.floor] = 0;
        }
        break;
    default:
        break;
    }
}

bit can_open()
{
    if (elevator_button_status[ELEVATOR.floor] == 1)
    {
        return 1;
    }

    if ((ELEVATOR.status == ELEVATOR_STATUS_UP) && (floor_button_status_up[ELEVATOR.floor] == 1))
    {
        return 1;
    }

    if ((ELEVATOR.status == ELEVATOR_STATUS_DOWN) && (floor_button_status_down[ELEVATOR.floor] == 1))
    {
        return 1;
    }

    return 0;
}

bit can_move_up()
{
    unsigned char i;
    for (i = ELEVATOR.floor; i < sizeof(elevator_button_status); i++)
    {
        if (elevator_button_status[i] == 1)
        {
            return 1;
        }
    }

    for (i = ELEVATOR.floor; i < sizeof(floor_button_status_up); i++)
    {
        if (floor_button_status_up[i] == 1)
        {
            return 1;
        }
    }

    for (i = ELEVATOR.floor; i < sizeof(floor_button_status_down); i++)
    {
        if (floor_button_status_down[i] == 1)
        {
            return 1;
        }
    }
    return 0;
}

bit can_move_down()
{
    unsigned char i;
    for (i = 0; i < ELEVATOR.floor; i++)
    {
        if (elevator_button_status[i] == 1)
        {
            return 1;
        }
    }

    for (i = 0; i < ELEVATOR.floor; i++)
    {
        if (floor_button_status_up[i] == 1)
        {
            return 1;
        }
    }

    for (i = 0; i < ELEVATOR.floor; i++)
    {
        if (floor_button_status_down[i] == 1)
        {
            return 1;
        }
    }
    return 0;
}

void elevator_led_light()
{
    LED_FLOOR_1 = 1;
    LED_FLOOR_2 = 1;
    LED_FLOOR_3 = 1;
    LED_FLOOR_4 = 1;
    switch (ELEVATOR.floor)
    {
    case 0:
        LED_FLOOR_1 = 0;
        break;
    case 1:
        LED_FLOOR_2 = 0;
        break;
    case 2:
        LED_FLOOR_3 = 0;
        break;
    case 3:
        LED_FLOOR_4 = 0;
        break;
    default:
        break;
    }
}

// unsigned char elevator_button_status[] = {0, 0, 0, 0};
// unsigned char floor_button_status_up[] = {0, 0, 0, 0};
// unsigned char floor_button_status_down[] = {0, 0, 0, 0};
void elevator_move()
{
    printf("%d\n", (int)ELEVATOR.floor);
    printf("%d\n", (int)ELEVATOR.status);
    print_arr(floor_button_status_down);
    print_arr(floor_button_status_up);
    print_arr(elevator_button_status);

    if (can_open())
    {
        elevator_open();
    }
    else
    {
        elevator_led_light();
    }

    // 当前所在的楼层，当前的运行状态。
    switch (ELEVATOR.status)
    {
    case ELEVATOR_STATUS_UP:
        if (can_move_up())
        {
            ELEVATOR.floor++;
        }
        else if (can_move_down())
        {
            ELEVATOR.status = ELEVATOR_STATUS_DOWN;
        }
        else
        {
            ELEVATOR.status = ELEVATOR_STATUS_WAITING;
        }
        break;
    case ELEVATOR_STATUS_DOWN:
        if (can_move_down())
        {
            ELEVATOR.floor--;
        }
        else if (can_move_up())
        {
            ELEVATOR.status = ELEVATOR_STATUS_UP;
        }
        else
        {
            ELEVATOR.status = ELEVATOR_STATUS_WAITING;
        }
        break;
    case ELEVATOR_STATUS_WAITING:
        if (can_move_up())
        {
            ELEVATOR.status = ELEVATOR_STATUS_UP;
        }
        else if (can_move_down())
        {
            ELEVATOR.status = ELEVATOR_STATUS_DOWN;
        }
        break;
    default:
        break;
    }
}

void main()
{
    unsigned char i;
    uart_init();
    init_key_config();
    ELEVATOR.floor = 0;
    ELEVATOR.status = ELEVATOR_STATUS_WAITING;

    // printf("%d\n", (int)sizeof(elevator_button_status));
    while (1)
    {
        elevator_move();
        for (i = 0; i < 5; i++)
        {
            delay_ms(200);
            process_button();
        }
    }
}